/**
 * File: Treat.java
 * Author: Eliana Feasley and Mark pallone
 * Emails: elf4@umbc.edu , markpa1@umbc.edu
 * Date: Jun 19, 2011
 * 
 * Description: Abstract treat class defining basic properties of all Treats. 
 */
package model;

import java.util.ArrayList;

import store.TaxCalculator;

/**
 * @author mark
 *
 */
public abstract class Treat {
	protected Container container;
	protected ArrayList<Flavor> flavorList;
	protected ArrayList<Topping> toppingList;
	
	/**
	 * setContainer - set container
	 * Preconditions: none
	 * Postconditions: the container will be returned
	 * @param container the container to set
	 */
	public void setContainer(Container container) {
		this.container = container;
	}
	
	/**
	 * 
	 * prepareIngredients - return how to prepare this treat. This is an accumulation of the strings returned by the abstract methods in this class: 
	 * 
	 * getTreatType()
	 * getOtherBeginningInstructions()
	 * getContainerInstruction()
	 * getFlavorInstruction()
	 * getToppingInstruction()
	 * getOtherFinalInstructions()
	 * 
	 * and an implementation of the Template design pattern. 
	 * 
	 * Preconditions: none
	 * Postconditions: how to prepare this treat will be returned
	 * @return how to prepare this treat
	 */
	public String prepareIngredients() {
		String instructions = "";
		
		if (!getTreatType().equals("")) {
			instructions += getTreatType() + "\n";
		}
		if (!getOtherBeginningInstructions().equals("")) {
			instructions += getOtherBeginningInstructions() + "\n";
		}
		if (!getContainerInstruction().equals("")) {
			instructions += getContainerInstruction() + "\n";
		}
		if (!getFlavorInstruction().equals("")) {
			instructions += getFlavorInstruction() + "\n";
		}
		if (!getToppingInstruction().equals("")) {
			instructions += getToppingInstruction() + "\n";
		}
		if (!getOtherFinalInstructions().equals("")) {
			instructions += getOtherFinalInstructions() + "\n";
		}
		
		return instructions;
	}

	/**
	 * 
	 * getTreatType - One sentence/statement summary of what this treat is, eg:
	 * "Preparing Vanilla and Strawberry Sundae with Whipped Cream, 
	 * Fresh Strawberries and Maraschino Cherry"
	 * 
	 * Preconditions: none
	 * Postconditions: the treat type to be created is returned
	 * @return the treat type to be created
	 */
	abstract public String getTreatType(); 
	
	/**
	 * 
	 * getOtherBeginningInstructions - get other instructions that may occur before container, flavor, and topping instructions
	 * Preconditions: none
	 * Postconditions: Other instructions that may occur before container, flavor, and topping instructions are returned
	 * @return other instructions that may occur before containre, flavor, and topping instructions
	 */
	public String getOtherBeginningInstructions(){
		return "";
	}
	
	/**
	 * 
	 * getContainerInstruction - What to do in order to prepare the treats container, eg:
	 * "Get bowl." 
	 * 
	 * Preconditions: none 
	 * Postconditions: the container preparation instruction is returned
	 * @return the container preparation instruction
	 */
	public String getContainerInstruction() {
		return "get a " + getContainer().toString();
	}
	/**
	 * getFlavorInstruction - What to do to prepare the flavors of the treat, eg:
	 * "Scoop 1 2.5-ounce scoop of strawberry ice cream and put in bowl.
	 * Scoop 1 2.5-ounce scoop of vanilla ice cream and put in bowl. 
	 * Put one spoonful of fresh strawberries on ice cream."
	 * 
	 * Preconditions: none
	 * Postconditions: the flavor preparation instruction is returned
	 * @return the flavor preparation instruction
	 */
	public String getFlavorInstruction() {
		ArrayList<Flavor> flavors = getFlavorList();
		String instruction = "";
		for (Flavor flav : flavors) {
			instruction += "dispense " + flav.getWeightPerServing() + " ounces of " + flav.toString() + "\n";
		}
		return instruction;
	}
	
	/**
	 * 
	 * getToppingInstruction - What to do to prepare the toppings of the treat, eg:
	 * "Put Whipped cream on ice cream
	 * Put Maraschino cherry on top" 
	 *  
	 * Preconditions: none
	 * Postconditions: the topping preparation instructions are returned
	 * @return the topping preparation instructions
	 */
	public String getToppingInstruction() {
		ArrayList<Topping> toppings = getToppingList();
		String instruction = "";
		for (Topping topping : toppings) {
			instruction += "add a splash of " + topping.toString() + "\n";
		}
		return instruction;
	}
	
	/**
	 * 
	 * getOtherFinalInstructions - Any other final instructions a treat may need, eg:
	 * Preconditions: none
	 * Postconditions: any other final instructions are returned
	 * @return any other final instructions 
	 */
	public String getOtherFinalInstructions(){
		return "";
	}
	
	/**
	 * 
	 * getPrice - get the total cost of this treat
	 * Preconditions: none
	 * Postconditions: the total cost of this treat is returned
	 * @return the total cost of this treat
	 */
	public double getPrice() {
		double totalCost = 0.0;
		
		// accumulate total
		for (Flavor flavor : flavorList) {
			totalCost += flavor.getPrice();
		}
		for (Topping topping : toppingList) {
			totalCost += topping.getPrice();
		}
		totalCost += container.getPrice();
		
		return totalCost;
	}
	
	/**
	 * getContainer - get the container
	 * Preconditions: none
	 * Postconditions: the container will be returned
	 * @return the container
	 */
	public Container getContainer() {
		return container;
	}
	/**
	 * setFlavorList - set flavorList
	 * Preconditions: none
	 * Postconditions: the flavorList will be returned
	 * @param flavorList the flavorList to set
	 */
	public void setFlavorList(ArrayList<Flavor> flavorList) {
		this.flavorList = flavorList;
	}
	/**
	 * getFlavorList - get the flavorList
	 * Preconditions: none
	 * Postconditions: the flavorList will be returned
	 * @return the flavorList
	 */
	public ArrayList<Flavor> getFlavorList() {
		return flavorList;
	}
	/**
	 * setToppingList - set toppingList
	 * Preconditions: none
	 * Postconditions: the toppingList will be returned
	 * @param toppingList the toppingList to set
	 */
	public void setToppingList(ArrayList<Topping> toppingList) {
		this.toppingList = toppingList;
	}
	/**
	 * getToppingList - get the toppingList
	 * Preconditions: none
	 * Postconditions: the toppingList will be returned
	 * @return the toppingList
	 */
	public ArrayList<Topping> getToppingList() {
		return toppingList;
	}
	
	public String getName(){
		// <Flavor, Flavor and Flavor> <Type> with <Topping, Topping, and Topping> in a <Container>
		String name = "";
		name += listToString(flavorList) + " ";
		name += getTreatType();
		if (toppingList.size() > 0)
			name += " with " + listToString(toppingList);
		name += " in a " + container.toString();
		return name;
	}
	
	
	private String listToString(ArrayList l){
		String string = "";
		ArrayList list = (ArrayList) l.clone();
		if (list.size() > 1){
            while (list.size() > 2)
			   string += list.remove(0).toString() + ", ";
            string += list.remove(0).toString() + " ";
            string += "and ";
		}
		
		if (list.size() == 1)
			string += list.remove(0).toString();
		
		
		
		return string;
				
	}
	
}
